home *** CD-ROM | disk | FTP | other *** search
- /*
- SoftBoot V3.31 for any A3000/68030 or 68040 system; Tested OK
- if run in startup-sequence on an A4000.
-
- by Greg Tibbs 10/25/1992 ; some code from SetCPU V1.4 by Dave Haynie
-
- MAIN PROGRAM
-
- Assumptions: The 040 for the A3000 only works under 2.0+, so there are
- assumptions that exec knows about an 040, that ROMsize
- is 512K. ZorroIII space is automatically found and MMU
- tables allocated and initialized. ZorroII caching
- defaults to on unless explicitly turned off or a
- BridgeBoard is found in the system. Compiled using
- SAS/C V6.00. Assembly module SofTag.asm must be
- linked in. The Assembly module has the magic to
- perform reboot recovery as well as talk to the 030
- and 040 MMUs directly.
-
- */
-
- #define PROGRAM_VERSION "V3.31"
-
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <exec/memory.h>
- #include <libraries/configvars.h>
- #include <proto/all.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <fcntl.h>
-
- #include "proto.h"
-
- #define ROUND030 0x00008000L
- #define ROUND 0x00002000L
- #define ROMSIZE 0x00080000L
- #define BONUSSIZE1_3 0x00045000L
- #define FASTROMLOC 0x07f80000L
- #define BASEROMLOC 0x00f80000L
- #define TABSIZE (128L * sizeof(ULONG))
- #define LEV3TABSIZE 0x2000L
- #define Z3STARTADDR 0x10000000L
- #define Z3ENDADDR 0xffffffffL
- #define WALL 0x100L
- #define WALLSIZE 2*WALL
- #define PFLUSHA040 0xf518
- #define CINVA040 0xf4d8
- #define MOVEC 0x4e7b
- #define NOP 0x4e71
- #define TCMASK030 0x80000000L
- #define FASTROMADDRMASK 0x7000000L
- #define MMU030TABLESIZE 0x8000L
- #define Z3L3SIZEPERBLOCK 0x4000L
- #define Z3L2SIZEPERBLOCK 0X200L
- #define PAGESIZE030 0X80000L
- #define PDTRESIDENT 0x01L
- #define UDTRESIDENT 0x03L
- #define CM_GLOBAL 0x400L
- #define WR_PROTECT 0x04L
- #define CM_COPYBACK 0x020L
- #define CM_INH_SER 0x040L
- #define CM_INH_NONSER 0x060L
- #define L1MASK ~0x1ffL /* Masks used in MMU table addresses for Level 1, 2 & 3 tables */
- #define L2MASK ~0x7fL
- #define L3MASK ~0x1fffL
-
- int CXBRK(void) {return(0L);}
-
- /* External Variables */
-
- extern struct ExecBase *SysBase;
-
- /* Communication to the assembly module is via common
- memory areas, rather than passing the data on the stack or via
- a register. */
-
- __far extern ULONG PhyRomStart, LogRomStart, SRP, CRP0;
- __far extern ULONG CRP1, TC030;
- __far extern ULONG StartRom, BusErr, CatchRom, Z3cache;
- __far extern ULONG TC, MemListArray[24], NumMemAreas;
- __far extern ULONG GetTC030(void), GetTC040(void), GetCPUType(void);
- __far extern void MyColdReboot(void), JTRom(void), SpeedRom(void), MakeRomTag(void);
- __far extern void JTRom13030(void), MakeRomTag13(void), ForceTTX(void);
- __far extern void KillRomTags(void), SF_Supervisor(void), CachesOff(void);
-
- struct ConfigureIt
- {
- ULONG StartAddr;
- ULONG EndAddr;
- ULONG BridgeBoard;
- };
-
- /* WallFreemem must be used to return all WALLed memory allocations */
-
- void WallFreeMem( void *Address, ULONG size)
- {
- Address=(void *)((ULONG)Address-WALL);
- size += WALLSIZE;
- FreeMem(Address,size);
- }
-
- /* KillRomTags() is an assembly function to overwrite the ID so leftover
- copies of the romtags embedded in this executable won't accidentially get
- found and run on reboot. Fastrom in particular was dangerous as if
- the romtag was found in RAM which was loaded during the fastrom operation,
- the MMU might get setup with a working MMU environment which would get
- stomped on as soon as any program overwrites that area as the MMU memory
- areas would not be autoallocated and protected. The Ram occupied by the
- romtag would not be protected either, BTW.
-
- A Real RomTag is only made when it is intended to softload a new
- operating system. Currently, the romtag must be in a list in ExecBase,
- or in special areas of ram to be autodetected, but the romtag IDs are
- obliterated just in case of future OS change where other areas may
- be autodetected. In any situation that exit() is to be called, we are
- going to return to the OS, and not softload, so the IDs are overwritten
- to be safe. */
-
- void exit2(ULONG error)
- {
- KillRomTags();
- exit(error);
- }
-
- /* MyExit returns RAM allocated for the ROM before exiting */
-
- void MyExit(error,TempROM)
- ULONG error, *TempROM;
- {
- if((ULONG)TempROM==FASTROMLOC)
- {
- FreeMem((ULONG *)FASTROMLOC,ROMSIZE);
- }
- else
- {
- if(TempROM) WallFreeMem(TempROM,ROMSIZE);
- }
- exit2(error);
- }
-
- /* TableFill13 build 68040 MMU tables for a 1.3 Bonus kickstart image.
- This improved version writes the 040 MMU tables into the temporary
- ram covered by the 1.3 rom image, rather than at the final address (unless
- they coinside). This allows me to delay Disable()ing the system until
- much later, and to not corrupt any possible previous rom or data at
- 7f80000-7ffffff until I am very close to rebooting. */
-
- void TableFill13(TempROM, cache)
- ULONG *TempROM, cache;
- {
- ULONG *TempTable, PageField;
- int i;
- /*
- The 1.3 bonus is very sneaky. It is setup with built-in 030 MMU tables,
- and code to add the motherboard fast ram, read the real time clock and
- to start the hard drives. The 1.3 ROM and Bonus is more than 256K but
- less than 512K. There is plenty of room to add 68040 MMU tables as well.
- The area from 7f80000 to 7fbffff is standard 256K 1.3 kickstart. MMU tables
- map, or mirror that to f80000 to fbffff and to fc0000 to ffffff, to make
- it look like a standard ROM system. The area in 7fc0000 to 7ffffff is
- mapped to f00000 to f7ffff. 1.3 Kickstart will read this area for any
- romtags; they do not have to be linked into any system list as with other
- locations. In the mirror is a romtag which initializes the clock, ram, and
- hard drive. In the assembly module, I built my own romtag, which
- SetFunction()s ColdCapture(). 2.0 and later exec honors the 1.3 execbase
- structure and will run the 1.3 execbase ColdCapture() vector before it
- realizes that it is not a 2.0+ execbase and relocates it. My Romtag
- then reloads the MMU and jumps back into 1.3, providing hardware
- (Keyboard) reboot recovery. Obviously anything which overwrites
- ColdCapture() without chaining it will cause the hardware reboot
- recovery process to fail. As a result, I blast my vector in (I do not
- chain) each time the romtag is run.
- */
- /* Calculate Pointer to 1st level MMU table in temporary RAM */
-
- TempTable = (ULONG *)(0x46000L + (ULONG)TempROM);
-
- /*Fill 1st level table */
-
- for (i = 1; i < 128; i++) *(TempTable+i) = 0L;
-
- /* Point entry for lowest 32 Meg block to 2nd level table */
-
- *TempTable = ((0x7fc8000L & L1MASK) | UDTRESIDENT); /* Point to Level 2 Table */
-
- /* Calculate 2nd Level table location in temporary ROM space */
-
- TempTable = (ULONG *)(0x48000L + (ULONG)TempROM);
-
- /* Fill in 2nd level table with pointers to 3rd level table */
-
- for (i=64; i<128; i++) *(TempTable+i)=0L;
- for (i=0; i<64; i++)
- *(TempTable+i)=(((0x7fca000L+i*128) & L2MASK) | UDTRESIDENT);
-
- /* Calculate 3rd level table address */
-
- TempTable = (ULONG *)(0x4a000L + (ULONG)TempROM);
-
- /* Fill in 3rd level table for lowest 15 Meg */
-
- PageField = CM_GLOBAL | CM_INH_SER | PDTRESIDENT;
- for (i=0; i<1984; i++) /*Romaddr/pagesize = 0xf80000/0x2000 = 1984 pages*/
- *(TempTable+i) = (((8192L*i) & L3MASK) | PageField);
-
- /* Turn on Z2 caching, if asked for */
-
- if(cache>0)
- {
- PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
- for(i=256; i<1280; i++) *(TempTable+i)=(((8192L*i) & L3MASK) | PageField);
- }
-
- /* Do ROM area, make write protected */
-
- PageField = CM_GLOBAL | CM_COPYBACK | WR_PROTECT | PDTRESIDENT;
- for (i=0; i<64; i++) /* Romsize/pagesize = 512K/8K = 64 pages */
- *(TempTable+i+1984)=(((FASTROMLOC+(8192L*i)) & L3MASK) | PageField);
-
- /* Fold over 7fc0000-7ffffff into F00000-F7ffff so romtags can be found */
-
- PageField = CM_GLOBAL | CM_COPYBACK | WR_PROTECT | PDTRESIDENT;
- for (i=0; i<32; i++)
- *(TempTable+i+2016)=(((FASTROMLOC+(8192L*i)) & L3MASK) | PageField);
-
- /* Make the area from f80000 to fc0000 mirror at fc0000 - ffffff */
-
- PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
- for (i=0;i<32;i++)
- *(TempTable+i+1920)=(((0x7fc0000L+(8192L*i)) & L3MASK) | PageField);
- }
-
- /* TableFill is the general purpose MMU table fill algorithm and requires
- considerably more information. The Pointers to the MMU tables must
- point to properly allocated and aligned memory space. */
-
- void
- TableFill(MMUTable, MMUTable2, MMUTable3, Z3MMUTable2, Z3MMUTable3, ROMADDR,
- cache2, cache3, MyConfigStruct, numblocks)
- ULONG *MMUTable, *MMUTable2, *MMUTable3, *Z3MMUTable2, *Z3MMUTable3,
- ROMADDR, cache2, cache3, numblocks;
- struct ConfigureIt *MyConfigStruct;
- {
- ULONG PageField;
- int i,j;
-
- /* The MMU address translation tree has been optimized into three memory
- areas for memory defragmentation purposes. The upper level is 128
- 32 bit pointers. These must be adjacent, by definition. However,
- the second and third level tables do not. Once allocated on a suitable
- boundary, all 2nd and 3rd level tables are adjacent in two blocks of
- RAM. The same technique is used later for Zorro III MMU tables */
-
- /* Each element of MMUTable[n] points to a 2nd level table representing
- 32 Megabytes. We only care about the lowest 16 Meg, so zero out
- all but the first entry */
-
- for (i = 1; i < 128; i++) *(MMUTable+i) = 0L;
-
- *MMUTable = (((ULONG)MMUTable2 & L1MASK) | UDTRESIDENT); /* Point to Level 2 Table */
-
- /* 2nd Level Table initialization for lowest 32 Meg. There are
- 128 entries in the 2nd level table, each pointing to a
- third level table which, in this MMU setup, contains the
- translated addresses for each block of memory. */
-
- /* Zero out pointers to 3rd level tables for upper 16 Meg block */
-
- for (i=64; i<128; i++) *(MMUTable2+i)=0L;
-
- /*Set 2nd Level pointers to 3rd level tables covering lowest 16 Meg. */
-
- for (i=0; i<64; i++)
- *(MMUTable2+i)=(((ULONG)&MMUTable3[i*32] & L2MASK) | UDTRESIDENT);
-
- /* Set up 3rd level Tables for lowest 16 Meg. Each third
- Level table represents 256K. */
-
- /* Since, in this implementation, all third level tables reside adjacent
- to one another, a total of 2048 8K (2K*8K = 16M) entries exist. The
- following 'for' loops takes advantage of this fact for table
- initialization purposes */
-
- /* Do from 0 to just prior to ROM (All non-cacheable)*/
-
- PageField = CM_GLOBAL | CM_INH_SER | PDTRESIDENT;
- for (i=0; i<1984; i++) /*Romaddr/pagesize = 0xf80000/0x2000 = 1984 pages*/
- *(MMUTable3+i) = (((8192L*i) & L3MASK) | PageField);
-
- /* Do ROM area, make write protected */
-
- PageField = CM_GLOBAL | CM_COPYBACK | WR_PROTECT | PDTRESIDENT;
- for (i=0; i<64; i++) /* Romsize/pagesize = 512K/8K = 64 pages */
- *(MMUTable3+i+1984)=(((ROMADDR+(8192L*i)) & L3MASK) | PageField);
-
- /* Turn on Z2 caching, if asked for */
-
- if(cache2>0)
- {
- PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
- for(i=256; i<1280; i++) *(MMUTable3+i)=(((8192L*i) & L3MASK) | PageField);
- }
-
- /* ZorroIII initialization */
-
- if(MyConfigStruct->StartAddr>=Z3STARTADDR)
- {
- /* Level 1 Table Generation for Zorro III area; Tables are
- built regardless of the Transparent Translation Registers */
-
- /* Assumption: MyConfigStruct->StartAddr is on a 32Meg Boundary
- (FindZorro3Start() ensures this). Any Board less
- than 32 Meg will generate a 32 MB MMU table for Zorro
- III areas */
-
- for(i=0;i<numblocks;i++)
- *(MMUTable+(MyConfigStruct->StartAddr/0x02000000L)+i)=
- ((((ULONG)Z3MMUTable2+i*0x200L) & L1MASK) | UDTRESIDENT);
-
- /* Level 2 Tables for Zorro III space */
-
- for (i=0L;i<(128L*numblocks);i++)
- {
- *(Z3MMUTable2+i)=
- (((ULONG)&Z3MMUTable3[i*32] & L2MASK) | UDTRESIDENT);
-
- /* Level 3 Tables for Zorro III space */
-
- PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
- if(!cache3) PageField = CM_GLOBAL | CM_INH_SER | PDTRESIDENT;
-
- for (j=0L; j<32L; j++)
- *(Z3MMUTable3+i*32L+j) =
- (((8192L*(32L*i+j)+MyConfigStruct->StartAddr) & L3MASK) | PageField);
- }
- }
- }
-
- /* FindZorro3Start() determines whether or not a Bridgeboard exists and
- and determines upper and lower bounds for MMU tables to cover
- the Zorro III ram and I/O cards. The start address is rounded down to
- the next lowest 32 MB boundary if it is not on one. The end address is
- rounded up to the next higher 32 MB boundary if not on one. The MMU
- tables must be filled in a 32 MB increment, so this is a valid choice */
-
- ULONG FindZorro3Start(struct ConfigureIt *MyConfigStruct)
- {
- ULONG temp;
- struct ConfigDev *myCD=NULL;
- struct Library *ExpansionBase = NULL;
- struct MemHeader *mem;
-
- MyConfigStruct->StartAddr = Z3ENDADDR;
- MyConfigStruct->EndAddr = 0L;
- MyConfigStruct->BridgeBoard = 0L;
-
- if((ExpansionBase=OpenLibrary("expansion.library",0L))==NULL)
- {
- MyConfigStruct->StartAddr = 0L;
- return(0L);
- }
-
- /* Loop though autoconfigured boards */
-
- while(myCD=FindConfigDev(myCD,-1L,-1L))
- {
- /* Check and mark if Bridgeboard is found */
-
- if(myCD->cd_Rom.er_Manufacturer==0x201 && myCD->cd_Rom.er_Product==1)
- MyConfigStruct->BridgeBoard=1L;
-
- /* Check for a Zorro III board (any type). Z3STARTADDR = 0x10000000 */
-
- if ((ULONG)(myCD->cd_BoardAddr) >= Z3STARTADDR)
- {
- /* Check for board less than Z3 end address; In case the OS
- does not store the config items in increasing order,
- or in a random order */
-
- if ((ULONG)(myCD->cd_BoardAddr) < MyConfigStruct->StartAddr)
- MyConfigStruct->StartAddr = (ULONG)(myCD->cd_BoardAddr);
-
- /* I am assuming that when you take a previous board address and
- add its length, you will get the address of the next board,
- therefore, I test with >= rather than > in the following statement: */
-
- if ((ULONG)(myCD->cd_BoardAddr) >= MyConfigStruct->EndAddr)
- {
- /* I am not sure how Slot Size and Board Size relate. I have seen
- a Progressive Zorro III ram card which only had 16 of 64 Meg
- populated. In that case 64K * SlotSize and BoardSize did not
- agree. To be conservative, I will take the larger range of the
- two. This ensures that the area will be covered, although it might
- be a bit much. */
-
- if(65536L*(ULONG)myCD->cd_SlotSize > (ULONG)myCD->cd_BoardSize)
- {
- MyConfigStruct->EndAddr =
- (ULONG)(myCD->cd_BoardAddr) +
- 65536L*(ULONG)(myCD->cd_SlotSize);
- }
- else /* BoardSize > than 64K * SlotSize */
- {
- MyConfigStruct->EndAddr =
- (ULONG)(myCD->cd_BoardAddr) +
- (ULONG)(myCD->cd_BoardSize);
- }
- }
- }
- }
-
- /* This code double checks the memory lists against my board config sizing
- logic above. Should a ZorroIII memory board not correctly work due to the
- above logic, it should be found via the memory lists and corrected.
- Zorro III space is defined as anywhere between 0x10000000 and 0xffffffff */
-
- /* Prevent anyone from walking the memory lists while we are using them */
-
- Forbid();
-
- /* Get pointer to system memory lists */
-
- mem=(struct MemHeader *)(SysBase->MemList.lh_Head);
-
- /* Loop until all nodes have been checked */
-
- while (mem->mh_Node.ln_Succ)
- {
- /* Check lower bounds of memory area against the beginning of Zorro III
- space and the lowest Zorro III address detected */
-
- if((ULONG)mem->mh_Lower >= Z3STARTADDR)
- {
- if( (ULONG)mem->mh_Lower < MyConfigStruct->StartAddr)
- {
- MyConfigStruct->StartAddr = (ULONG)(mem->mh_Lower);
- }
-
- /* Check upper memory list bounds against the largest Z3 board found */
-
- if((ULONG)mem->mh_Upper > MyConfigStruct->EndAddr)
- {
- MyConfigStruct->EndAddr = (ULONG)(mem->mh_Upper);
- }
- }
-
- /* Go to next node in memory list */
-
- mem=(struct MemHeader *)(mem->mh_Node.ln_Succ);
- }
-
- /* We are done, so let system continue */
-
- Permit();
-
- /* If StartAddr was never modified, then there is no Zorro III ram or I/O
- in this system and set it to a value other routines will detect */
-
- if(MyConfigStruct->StartAddr == Z3ENDADDR) MyConfigStruct->StartAddr=0L;
- CloseLibrary(ExpansionBase);
-
- /* Now round start and end address to nearest full 32 MB increment */
-
- if(MyConfigStruct->StartAddr >= Z3STARTADDR)
- {
- /* The following code will round StartAddr to the next lowest 32MB boundary
- if it is not already on one. */
-
- MyConfigStruct->StartAddr = MyConfigStruct->StartAddr/0x02000000L;
- MyConfigStruct->StartAddr *= 0x02000000L;
-
- /* We want to round the end address up to the next higher 32 MB boundary
- if it does not end on a 32 MB boundary. */
-
- temp = MyConfigStruct->EndAddr/0x02000000L;
- temp *= 0x02000000L;
- if (temp != MyConfigStruct->EndAddr) MyConfigStruct->EndAddr = temp + 0x02000000L;
- }
- return (0L);
- }
-
- /* This replaces the Lattice "stricmp()" function, plus it's a better form
- for my needs here. */
-
- static BOOL striequ(s1,s2)
- char *s1,*s2;
- {
- BOOL aok;
-
- while (*s1 && *s2 && (aok = (*s1++ & 0xdf) == (*s2++ & 0xdf)));
- return (BOOL) (!*s1 && aok);
- }
-
- /* Page tables and other MMU stuff must be on a page sized boundary, and
- that boundary must be a power of two. This routine allocates such an
- aligned block of memory. */
-
- /* AllocAligned now allocates a 32 byte wall around the the Allocation to
- help protect against memlist tail overwrites and other programs which
- overrun their adjacent memory allocations. The address returned is the
- 'safe' aligned address. 32 bytes before and 32+size bytes past the
- 'safe' address are allocated. */
-
- void *AllocAligned(size,bound)
- ULONG size;
- ULONG bound;
- {
- void *mem, *aligned;
- ULONG length;
-
- length=size+bound+WALLSIZE;
- if (!(mem = (void *)AllocMem(length,MEMF_FAST))) return NULL;
- Forbid();
- aligned = (void *)((((ULONG)mem + bound - 1) & ~(bound - 1))-WALL);
- FreeMem(mem,length);
- mem = (void *)AllocAbs(size+WALLSIZE,aligned);
- Permit();
- mem=(void *)((ULONG)mem+WALL);
- return mem;
- }
-
- void PatchRom(RomAddr)
- ULONG *RomAddr;
- {
- ULONG i,DStart, *LTemp;
- UWORD Test,*Start;
-
- LTemp=(ULONG *)(LogRomStart+4);
- DStart=(*(LTemp)-LogRomStart)+(ULONG)RomAddr;
- Start=(UWORD *)DStart;
-
- /* Patch # 1 - Remove Rom Checksum error branch */
-
- for(i=0;i<5000;i++) /* 5000 word limit from Start address for search */
- {
- if((Test=*(Start+i))==0x4685)
- if((Test=*(Start+i+1))==0x6600)
- {
- *(Start+i)=0x7A00; /* Patch out Rom checksum test */
- break; /* Not d5 -> moveq #0,d5 following branch test then*/
- } /* Error check Always passes! */
- }
-
- /* Patch # 2 - Prevent 040 mTTx registers from being blown away
- by patching in NOPS over offending opcodes */
-
- for(i=0;i<25000;i++) /*Search up to 25K words away from start for patch */
- {
- if(*(Start+i)==MOVEC)
- {
- /* Test for 0x4E7B0003 thru 0x4E7B0007 and 0x4E7B0805 thru 0x4E7B0807
- and change to 0x4E714E71 (Dual NOPs) */
-
- Test = *(Start+i+1) & 0xFFF;
- if(Test > 2 && Test < 8 || Test > 804 && Test < 808)
- {
- *(Start+i) = NOP;
- *(Start+i+1) = NOP;
- }
- }
- }
- }
-
- int main(argc,argv)
- int argc;
- char *argv[];
- {
- ULONG i, cpu, myTC, myTC30, file, cache, FastRom, numblocks;
- ULONG *MMUTable2,*MMUTable3, *ROM32, *MMUTable, *Z3MMUTable2, *Z3MMUTable3;
- ULONG Z3L2size, Z3L3size, *MMU030Table, both, Z3All, rm13, *TempROM;
- ULONG count, MMUOverride, enttx;
-
- struct ConfigureIt MyConfigStruct;
-
- /* If they're just asking for help */
-
- if (argc >= 2 && argv[1][0] == '?') {
- printf("\n\2337mSoftBoot %s\2330m [NOCACHEZ2][KILLROM][NOCATCHROM][ONETHREE]\n",
- PROGRAM_VERSION);
- printf(" [BOTH][SOFTBOOT][NOBUSERRORS][FASTROM]\n");
- printf(" [ENTTX][OVRMMU][NOCACHEZ3][Z3ALL]\n");
- exit2(0L);
- }
-
- enttx=0L; /* Flag for command line parsing for enttx option */
- rm13=0L; /* Not loading 1.3 Rom by default */
- both=0L; /* Not building both 030 and 040 MMU tables by default */
- cache=1L; /* Turn on Zorro II caching by default */
- Z3cache=1L; /* Turn on Zorro III caching by default */
- BusErr=0L; /* Do not turn off the bus error HW by default */
- FastRom=0L; /* Not performing just a fastrom */
- CatchRom=0L; /* Do not patch the exception handler for invalid access */
- MMUTable=NULL; /* Set Pointer to NULL */
- MMU030Table=NULL; /* Set Pointer to NULL */
- LogRomStart=BASEROMLOC; /* Logical ROM start address */
- ROM32 = (ULONG *)FASTROMLOC; /* Physical (relocated) Rom Address */
- MMUOverride=0L; /* Flag to override existing MMU setup */
- Z3All = 0L; /* Do not make 040 MMU tables for all of Z3 space */
-
- /* Search for Zorro III start address and length */
-
- (void)FindZorro3Start((struct ConfigureIt *)&MyConfigStruct);
-
- /* Find if there is a bridgeboard and turn off Z2 cache if so */
-
- if (MyConfigStruct.BridgeBoard) cache=0L;
-
- cpu=GetCPUType();
-
- /* Parse Command line */
-
- if (argc>1)
- {
- for(i=1;i<argc;i++)
- {
-
- if ((int)striequ(argv[i],"NOCACHEZ2")) cache=0L;
- if ((int)striequ(argv[i],"NOCACHEZ3")) Z3cache=0L;
- if ((int)striequ(argv[i],"ONETHREE")) {both=1L; rm13=1L;
- LogRomStart=0x00fc0000L;}
- if ((int)striequ(argv[i],"BOTH")) both=1L;
- if ((int)striequ(argv[i],"KILLROM")) {KillRomTags();
- MyColdReboot();}
- if ((int)striequ(argv[i],"NOBUSERRORS")) BusErr=1L;
- if ((int)striequ(argv[i],"FASTROM")) FastRom=1L;
- if ((int)striequ(argv[i],"NOCATCHROM")) CatchRom=1L;
- if ((int)striequ(argv[i],"SOFTBOOT")) {KillRomTags();
- ColdReboot();}
- if ((int)striequ(argv[i],"ENTTX")) if(cpu==68040L) enttx = 1L;
- if ((int)striequ(argv[i],"OVRMMU")) MMUOverride=1L;
- if ((int)striequ(argv[i],"Z3ALL")) Z3All=1L;
-
- }
- }
-
- if(enttx>0L) {ForceTTX(); exit2(0);}
-
- /* Let's Test as much as we can, before we get in too far to back out */
-
- printf("%ld CPU found.\n",cpu);
-
- if (cpu !=68020L && cpu != 68030L && cpu !=68040L)
- {
- printf("SoftBoot Requires a 68030 or 68040 CPU!\n");
- exit2(20L);
- }
-
- if(cpu==68020L) cpu=68030L; /* I'm assuming an '851 */
-
- myTC=0L;
- myTC30=0L;
- if(cpu==68040L) myTC=GetTC040();
- if(cpu==68030L) myTC30=GetTC030();
- if (!MMUOverride && ((cpu == 68040L && myTC) ||
- (cpu == 68030L && (myTC30 & TCMASK030))))
- {
- printf("FastRom MMU already in operation!\n");
- exit2(0L);
- }
-
- if(cache) printf("Zorro II area will be cached!\n");
-
- if (FastRom)
- {
- both=0L; /* Override Both parameter if Fastrom is called for */
-
- ROM32 = (ULONG *)AllocAligned(ROMSIZE,ROUND030);
- if(!ROM32)
- {
- printf("FASTROM Memory Allocation Failure! Reboot to defragment!\n");
- exit2(20L);
- }
- TempROM=ROM32;
- }
- else /* We're softbooting a new OS */
- {
- TempROM=AllocAbs(ROMSIZE,(APTR)FASTROMLOC);
- if(!TempROM)
- {
- TempROM=AllocAligned(ROMSIZE,0x1000L);
-
- /* Check for No memory or overlap with final destination */
-
- if (!TempROM || (((ULONG)TempROM+ROMSIZE+WALL >= FASTROMLOC) &&
- ((ULONG)TempROM & FASTROMADDRMASK)))
- {
- printf("TempROM Memory Allocation Failure. Reboot to defragment memory!\n");
- exit2(20L);
- }
- }
-
- /* The final ROM destination is FASTROMLOC (0x7f80000). At a later point, I
- will Disable() so I can stomp on this area without crashing someone else.
- So I copy the disk file to 0x7f80000 or a temporary buffer now if 0x7f80000
- was not directly available, so the read() will not break the Disable() and
- allow the system to crash and burn by having another task use memory
- I just overwrote. */
-
- if(!rm13)
- {
- file=open("devs:Kickstart",0L);
- if(file==-1L)
- {
- printf("Error opening devs:Kickstart!\n");
- close(file);
- MyExit(20L,TempROM);
- }
- count=read(file, TempROM, ROMSIZE);
- if(count != ROMSIZE)
- {
- printf("Devs:Kickstart wrong length!\n");
- close(file);
- MyExit(20L,TempROM);
- }
- }
- else
- {
- file=open("devs:Kickstart1.3",0L);
- if(file==-1L)
- {
- printf("Error opening devs:Kickstart1.3!\n");
- close(file);
- MyExit(20L,TempROM);
- }
- count=read(file, TempROM, BONUSSIZE1_3);
- if(count != BONUSSIZE1_3)
- {
- printf("Devs:Kickstart1.3 wrong length!\n");
- close(file);
- MyExit(20L,TempROM);
- }
- }
- }
-
- /* No need to turn caches off if fastromming */
-
- if(!FastRom)CachesOff();
-
- if ((cpu==68030L || both) && !rm13)
- {
- MMU030Table = (ULONG *)AllocAligned(MMU030TABLESIZE,ROUND030);
-
- if (!MMU030Table || !FastRom && ((ULONG)MMU030Table > Z3STARTADDR))
- {
- if(FastRom)
- {
- printf("Out of Memory For MMU tables! Reboot and Retry\n");
- }
- else
- {
- printf("No Memory on A3000|A4000 Motherboard for MMU tables! Reboot to defragment.\n");
- }
- MyExit(20L,TempROM);
- }
- }
-
- if(cpu==68040L || both)
- {
- numblocks=0L;
-
- if(!rm13 && MyConfigStruct.StartAddr>=Z3STARTADDR)
- {
- printf("Zorro III enabled via MMU at 0x%08lx\n",MyConfigStruct.StartAddr);
-
- /* Count Number of 32 Meg Blocks needed for Zorro III devices */
-
- if (MyConfigStruct.StartAddr >= Z3STARTADDR ) /* if there was Z3 Ram... */
- {
- /* Estimate number of 32 Megabyte RAM areas */
-
- numblocks = (MyConfigStruct.EndAddr - MyConfigStruct.StartAddr)/0x2000000L;
-
- /* Z3ALL flag forces all Zorro III ram to be mapped. This case is
- required if CBM moves start of Zorro III RAM or separates I/O
- space from ram space for 040 mTTx registers. In such a case, the
- old operating system's idea of Zorro III space would not match
- the new operating system, and faulty MMU tables would be built.
- The Z3ALL flag builds MMU tables at great expense in ram, but
- allows the new OS to work until a new softboot is made available.
-
- So, to make the Z3 routines map all of Z3 space, we set
- MyConfig.StartAddr to the beginning of Z3 space and set
- numblocks to cover the entire range. */
-
- if(Z3All > 0L)
- {
- numblocks=(Z3ENDADDR - Z3STARTADDR + 1L)/0x02000000L;
- MyConfigStruct.StartAddr=Z3STARTADDR;
- }
- }
- }
-
- Z3L3size=numblocks*Z3L3SIZEPERBLOCK; /*Third level tables' size */
- Z3L2size=numblocks*Z3L2SIZEPERBLOCK; /*Second Level Tables' size */
-
- NumMemAreas=3L; /* Number of areas to protect via Kickmemlist */
-
- /* Get the memory for the basic 68040 MMU tables. */
-
- if(!rm13)
- {
- MMUTable = (ULONG *)AllocAligned(TABSIZE,ROUND);
- MMUTable2 = (ULONG *)AllocAligned(TABSIZE,ROUND);
- MMUTable3 = (ULONG *)AllocAligned(LEV3TABSIZE,ROUND);
- Z3MMUTable2 = NULL;
- Z3MMUTable3 = NULL;
-
- /* Allocate Zorro III 2nd and third level tables */
-
- if(MyConfigStruct.StartAddr>=Z3STARTADDR)
- {
- Z3MMUTable2 = (ULONG *)AllocAligned(Z3L2size,ROUND);
- Z3MMUTable3 = (ULONG *)AllocAligned(Z3L3size,ROUND);
-
- /* Update KickMemList Tables for protection of Zorro III tables
- Note areas are protected via one WALL before and after actual
- Area used. */
-
- if(!FastRom)
- {
- MemListArray[6] = (ULONG)Z3MMUTable2-WALL;
- MemListArray[7] = Z3L2size+WALLSIZE;
- MemListArray[8] = (ULONG)Z3MMUTable3-WALL;
- MemListArray[9] = Z3L3size+WALLSIZE;
- NumMemAreas=5L; /* Now five memory areas to protect */
- }
- }
-
- /*
- Last safety check that all MMU tables were allocated. If not,
- return memory that was allocated and exit the program.
- For stability, when booting a new OS, the MMU tables must be
- in A3000|A4000 motherboard range, which are constant and
- available through reset. For FastRom, any RAM is OK.
- */
-
- if (!MMUTable || !MMUTable2 || !MMUTable3 ||
- !FastRom && ((ULONG)MMUTable > Z3STARTADDR) ||
- !FastRom && ((ULONG)MMUTable2 > Z3STARTADDR) ||
- !FastRom && ((ULONG)MMUTable3 > Z3STARTADDR) ||
- !FastRom && ((ULONG)Z3MMUTable2 > Z3STARTADDR) ||
- !FastRom && ((ULONG)Z3MMUTable3 > Z3STARTADDR) ||
- ((MyConfigStruct.StartAddr>=Z3STARTADDR) && (!Z3MMUTable3 || !Z3MMUTable2)))
- {
- if (both && MMU030Table) WallFreeMem(MMU030Table,MMU030TABLESIZE);
- if (MMUTable) WallFreeMem(MMUTable,TABSIZE);
- if (MMUTable2) WallFreeMem(MMUTable2,TABSIZE);
- if (MMUTable3) WallFreeMem(MMUTable3,LEV3TABSIZE);
- if (Z3MMUTable2) WallFreeMem(Z3MMUTable2,Z3L2size);
- if (Z3MMUTable3) WallFreeMem(Z3MMUTable3,Z3L3size);
- printf("No Memory on A3000|A4000 Motherboard for MMU tables! Reboot to defragment.\n");
- MyExit(20L,TempROM);
- }
-
- /* Setup KickMemList via MemListArray - Note Safety wall is included! */
-
- if(!FastRom)
- {
- MemListArray[0] = (ULONG)MMUTable-WALL;
- MemListArray[1] = TABSIZE+WALLSIZE;
- MemListArray[2] = (ULONG)MMUTable2-WALL;
- MemListArray[3] = TABSIZE+WALLSIZE;
- MemListArray[4] = (ULONG)MMUTable3-WALL;
- MemListArray[5] = LEV3TABSIZE+WALLSIZE;
-
- /* Now fill the MMU tables that we have successfully allocated -
- The final location of the new ROM will always be FASTROMLOC */
-
- TableFill(MMUTable, MMUTable2, MMUTable3, Z3MMUTable2, Z3MMUTable3,
- FASTROMLOC, cache, Z3cache,
- (struct ConfigureIt *)&MyConfigStruct, numblocks);
- }
- else /* Fill MMU tables for FastRom */
- {
- TableFill(MMUTable, MMUTable2, MMUTable3, Z3MMUTable2, Z3MMUTable3,
- (ULONG)TempROM, cache, Z3cache,
- (struct ConfigureIt *)&MyConfigStruct, numblocks);
- }
- }
- else /* rm13 */
- {
- /* Perform 1.3 MMU magic */
-
- TableFill13(TempROM, cache);
- MMUTable=(ULONG *)0x7fc6000L;
- }
- SRP = (ULONG)MMUTable;
- }
-
- if (cpu==68030L || both)
- {
- /* Fill 030 MMU tables */
-
- if(!rm13) /* Note 1.3 bonus builds KS1.3 030 MMU tables */
- {
- for (i=0;i<32;i++) MMU030Table[i]=((PAGESIZE030 * i) + 0x41L);
- for (i=32;i<8160;i++) MMU030Table[i]=((PAGESIZE030 * i) + 1L);
- for (i=8160;i<8192;i++) MMU030Table[i]=((PAGESIZE030 * i) + 0x41L);
- if (cache) for (i=4;i<21;i++) MMU030Table[i]=((PAGESIZE030 * i) + 1L);
- MMU030Table[31] = (ULONG)ROM32 | 5L;
-
- if(!FastRom) /*update kickmemList if we are booting a new OS */
- {
- if (both) /* 040 MMU tables are already loaded into the kickmemlist*/
- {
- MemListArray[NumMemAreas*2] = (ULONG)MMU030Table-WALL;
- MemListArray[NumMemAreas*2+1]= MMU030TABLESIZE+WALLSIZE;
- NumMemAreas++;
- }
- else /* Only the 030 table needs to be protected */
- {
- MemListArray[0]= (ULONG)MMU030Table-WALL;
- MemListArray[1]= MMU030TABLESIZE+WALLSIZE;
- NumMemAreas=1L;
- }
- }
- }
- }
-
- /* 030 MMU Register values */
-
- TC030 =0x80f0d400L;
- CRP0 =0x7fff0002L;
- CRP1 =(ULONG)(MMU030Table)&~0xfL;
- PhyRomStart= (ULONG)ROM32; /* Wrote into romtag, for its use */
-
- /* Now I have to set up the MMU. The Supervisor Root Pointer tells the MMU about
- the table I've set up, and the Translation Control register will turn
- the thing on. */
-
- if(!FastRom)
- {
- /* Softloading a new OS */
-
- if(rm13)
- {
- Disable();
- SF_Supervisor();
- CachesOff();
- if((ULONG)TempROM != FASTROMLOC)
- for(i=0;i<0x20000;i++) *((ULONG *)FASTROMLOC+i) = *(TempROM+i);
- MakeRomTag13();
- CachesOff();
- if(cpu!=68040L)
- {
- JTRom13030();
- }
- else
- {
- JTRom();
- }
- }
- else /* 2.0 or later */
- {
- PatchRom(TempROM);
- Disable();
- SF_Supervisor();
- MakeRomTag();
- if((ULONG)TempROM!=FASTROMLOC)
- for(i=0;i<0x20000;i++) *((ULONG *)FASTROMLOC+i) = *(TempROM+i);
- CachesOff();
- JTRom();
- }
- }
- else /* Fastrom Operation */
- {
- KillRomTags(); /* Blow away rontag headers so they can't ever be found */
- CopyMemQuick((ULONG *)BASEROMLOC,ROM32,ROMSIZE);
- CachesOff();
- SpeedRom();
- }
- exit(0L);
- }
-